package com.xxg.socket.impl;

import com.xxg.socket.YmaServer;
import com.xxg.socket.YmaSession;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * Created by game group on 2020/12/23.
 */
@ChannelHandler.Sharable
public abstract class SessionAbleYmaServer extends ChannelInboundHandlerAdapter implements YmaServer {
    private static final Logger log = LoggerFactory.getLogger(SessionAbleYmaServer.class);

    protected final ConcurrentHashMap<ChannelHandlerContext, YmaSession> sessions = new ConcurrentHashMap<>();

    /**
     * 接受client发送的消息
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        YmaSession session = sessions.get(ctx);
        Object res = onMessage(session, msg);
        send(session,res);
    }

    /**
     * 不懂
     *
     * 通知处理器最后的channelRead()是当前批处理中的最后一条消息时调用
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    /**
     * 捕获到异常
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        onError(sessions.get(ctx),cause);
        ctx.close();
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        YmaSession session = sessions.get(ctx);
        Object res = onClose(session);
        send(session,res);
        sessions.remove(ctx);
    }

    /**
     * 客户端连接
     *
     * 创建session
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        YmaSession session = new YmaSession();
        session.put("context",ctx);
        sessions.put(ctx,session);
        Object res = onOpen(session);
        send(session,res);
    }

    @Override
    public void send(YmaSession session, Object message) {
        if(null != message) {
            ((ChannelHandlerContext)session.get("context")).writeAndFlush(message);
        }else {
            if (log.isDebugEnabled()) {
                log.trace("message is null");
            }
        }
    }
}
